home *** CD-ROM | disk | FTP | other *** search
- From: Kay Roemer <roemer@informatik.uni-frankfurt.de>
- Posted-Date: Mon, 21 Mar 94 9:25:12 MEZ
- Received-Date: Mon, 21 Mar 94 09:25:12 +0100
- Message-Id: <9403210825.AA05871@hera.rbi.informatik.uni-frankfurt.de>
- Subject: addroottimeout() for Mint 1.10
- To: ersmith@netcom.com
- Date: Mon, 21 Mar 94 9:25:12 MEZ
- Mailer: Elm [revision: 70.85]
-
- The following diffs relative to Mint 1.10 implement the function
-
- TIMEOUT *addroottimeout (long delta, void (*func)(long), short flags);
-
- which is accessible by loadable device drivers and file systems trough
- `struct kerinfo'.
-
- It is used to attach a timeout to happen in `delta' milliseconds to
- the `root' process, ie MiNT.
-
- Remember that `addtimeout' attaches the timeout to the process which
- was active when addtimeout was called. This means the timeout will be
- cancelled if this process exits.
-
- Timeouts set with `addroottimeout' wont be cancelled this way. They
- always happen unless you cancel them explicitely with `canceltimeout'.
-
- Thus addroottimeout can be used by device drivers and file systems
- to maintain priodic tasks. Note that the timeout function can use
- all the functions provided by `struct kerinfo' (a separate process
- can't)!
-
- `addroottimeout' takes an additional argument `flags'. Currently
- only bit #0 is used. All other bits are reserved and have currently
- no meaning.
-
- The meaning of bit #0 is:
-
- bit #0 set: `addrootimeout' is called from interrupt. This makes
- `addroottimeout' avoid kmalloc() and use statically allocated
- memory for the TIMEOUT structure instead.
-
- bit #0 clear: not called from interrupt, can use kmalloc().
-
- Thus (if bit #0 of flags is set), `addroottimeout' can be called from
- interrupt. This makes it extremly useful for interrupt driven device
- drivers, for instance serial ones.
-
- Let us assume a driver receives characters interrupt driven. It maintains
- a flag `timeout_pending'. If a character arrives and this flag is not
- set, the driver adds a timeout using `addroottimeout' with flags&1 == 1,
- delta ~ 200 and sets the flag `timeout_pending'.
-
- Thus the timeout function will be called in about 200 ms. It resets
- the flag `timeout_pending' and then processes the arrived characters,
- does some time consuming jobs (sending signals and waking up processes,
- for instance) that cannot be done at interrupt time. It may use all the
- kernel functions in `struct kerinfo'.
-
- This is a only reasonable (no polling) method for hardware device
- drivers to use sleep() and wake() instead of nap().
-
- `addroottimeout' is also extensively used in MintNet, so I would love
- to see it included in Mint 1.11!
-
- Note that `addroottimeout' may return NULL when memory is low.
-
- As a side effekt, the diffs incorporate a fallback method for `addtimeout'
- when kmalloc() is out of memory.
-
- I also fixed `checkalarms' to decrease the `when' field of the head of
- the timeout list *before* calling the timeout function. Otherwise the
- timeout function could install another timeout, whose `when' field is
- then wronly decreased.
-
- So long,
- Kay.
-
- --8<----------------------------------------------------
- *** file.h.orig Tue Feb 22 19:30:10 1994
- --- file.h Mon Mar 7 21:43:10 1994
- ***************
- *** 243,251 ****
- /* functions for adding/cancelling timeouts */
- struct timeout * ARGS_ON_STACK (*addtimeout) P_((long, void (*)()));
- void ARGS_ON_STACK (*canceltimeout) P_((struct timeout *));
-
- /* reserved for future use */
- ! long res2[7];
- };
-
- /* flags for open() modes */
- --- 243,252 ----
- /* functions for adding/cancelling timeouts */
- struct timeout * ARGS_ON_STACK (*addtimeout) P_((long, void (*)()));
- void ARGS_ON_STACK (*canceltimeout) P_((struct timeout *));
- + struct timeout * ARGS_ON_STACK (*addroottimeout) P_((long, void (*)(), short));
-
- /* reserved for future use */
- ! long res2[6];
- };
-
- /* flags for open() modes */
- *** main.c.orig Fri Feb 11 19:37:16 1994
- --- main.c Tue Feb 22 19:32:52 1994
- ***************
- *** 193,199 ****
- strnicmp, stricmp, strlwr, strupr, ksprintf,
- ms_time, unixtim, dostim,
- nap, sleep, wake, wakeselect,
- ! denyshare, denylock, addtimeout, canceltimeout
- };
-
- /* table of processor frame sizes in _words_ (not used on MC68000) */
- --- 193,200 ----
- strnicmp, stricmp, strlwr, strupr, ksprintf,
- ms_time, unixtim, dostim,
- nap, sleep, wake, wakeselect,
- ! denyshare, denylock, addtimeout, canceltimeout,
- ! addroottimeout
- };
-
- /* table of processor frame sizes in _words_ (not used on MC68000) */
- *** proc.h.orig Tue Feb 22 17:35:32 1994
- --- proc.h Tue Feb 22 17:36:04 1994
- ***************
- *** 67,72 ****
- --- 67,73 ----
- struct proc *proc;
- long when;
- void (*func) P_((struct proc *)); /* function to call at timeout */
- + short flags;
- } TIMEOUT;
-
- #ifndef GENMAGIC
- *** proto.h.orig Tue Feb 22 19:34:14 1994
- --- proto.h Mon Mar 7 21:42:12 1994
- ***************
- *** 274,279 ****
- --- 274,280 ----
-
- /* timeout.c */
- TIMEOUT * ARGS_ON_STACK addtimeout P_((long delta, void (*func)(PROC *p)));
- + TIMEOUT * ARGS_ON_STACK addroottimeout P_((long delta, void (*func)(PROC *p), short flags));
- void ARGS_ON_STACK cancelalltimeouts P_((void));
- void ARGS_ON_STACK canceltimeout P_((TIMEOUT *which));
- void ARGS_ON_STACK timeout P_((void));
- *** timeout.c.orig Sat Feb 19 15:57:00 1994
- --- timeout.c Sat Mar 19 18:30:34 1994
- ***************
- *** 19,55 ****
- extern short in_kernel; /* in main.c */
-
- static void unnapme P_((PROC *));
-
- ! /*
- ! * addtimeout(long delta, void (*func)()): schedule a timeout for the current
- ! * process, to take place in "delta" milliseconds. "func" specifies a
- ! * function to be called at that time; the function is passed as a parameter
- ! * the process for which the timeout was specified (i.e. the value of
- ! * curproc at the time addtimeout() was called; note that this is probably
- ! * *not* the current process when the timeout occurs).
- */
- !
- ! TIMEOUT *tlist;
-
- - #define newtimeout() (TIMEOUT *)kmalloc(SIZEOF(TIMEOUT))
- - #define disposetimeout(t) kfree(t)
-
- ! TIMEOUT * ARGS_ON_STACK
- ! addtimeout(delta, func)
- ! long delta;
- ! void (*func) P_((PROC *));
- {
- ! TIMEOUT *t, **prev, *cur;
-
- ! t = newtimeout();
-
- ! /* BUG: we should have some fallback mechanism for timeouts when the
- ! kernel memory is exhausted
- ! */
- ! assert(t);
-
- ! t->proc = curproc;
- ! t->func = func;
-
- cur = tlist;
- prev = &tlist;
- --- 19,80 ----
- extern short in_kernel; /* in main.c */
-
- static void unnapme P_((PROC *));
- + static TIMEOUT *newtimeout P_((short));
- + static void disposetimeout P_((TIMEOUT *));
- + static void inserttimeout P_ ((TIMEOUT *, long));
- +
- + #define TIMEOUTS 20 /* # of static timeout structs */
- + #define TIMEOUT_USED 0x01 /* timeout struct is in use */
- + #define TIMEOUT_STATIC 0x02 /* this is a static timeout */
-
- ! /* This gets implizitly initialized to zero, thus the flags are
- ! * set up correctly.
- */
- ! static TIMEOUT timeouts[TIMEOUTS] = { { 0, }, };
- ! TIMEOUT *tlist = NULL;
-
-
- ! static TIMEOUT *
- ! newtimeout(fromlist)
- ! short fromlist;
- {
- ! TIMEOUT *t;
- ! short i, sr;
-
- ! if (!fromlist) {
- ! t = kmalloc(SIZEOF(TIMEOUT));
- ! if (t) {
- ! t->flags = 0;
- ! return t;
- ! }
- ! }
- ! sr = spl7();
- ! for (i = 0; i < TIMEOUTS; ++i) {
- ! if (!(timeouts[i].flags & TIMEOUT_USED)) {
- ! timeouts[i].flags |= (TIMEOUT_STATIC|TIMEOUT_USED);
- ! spl(sr);
- ! return &timeouts[i];
- ! }
- ! }
- ! spl(sr);
- ! return 0;
- ! }
-
- ! static void
- ! disposetimeout(t)
- ! TIMEOUT *t;
- ! {
- ! if (t->flags & TIMEOUT_STATIC) t->flags &= ~TIMEOUT_USED;
- ! else kfree(t);
- ! }
-
- ! static void
- ! inserttimeout(t, delta)
- ! TIMEOUT *t;
- ! long delta;
- ! {
- ! TIMEOUT **prev, *cur;
- ! short sr = spl7();
-
- cur = tlist;
- prev = &tlist;
- ***************
- *** 59,65 ****
- t->next = cur;
- t->when = delta;
- *prev = t;
- ! return t;
- }
- delta -= cur->when;
- prev = &cur->next;
- --- 84,91 ----
- t->next = cur;
- t->when = delta;
- *prev = t;
- ! spl(sr);
- ! return;
- }
- delta -= cur->when;
- prev = &cur->next;
- ***************
- *** 69,74 ****
- --- 95,167 ----
- t->when = delta;
- t->next = cur;
- *prev = t;
- + spl(sr);
- + }
- +
- + /*
- + * addtimeout(long delta, void (*func)()): schedule a timeout for the current
- + * process, to take place in "delta" milliseconds. "func" specifies a
- + * function to be called at that time; the function is passed as a parameter
- + * the process for which the timeout was specified (i.e. the value of
- + * curproc at the time addtimeout() was called; note that this is probably
- + * *not* the current process when the timeout occurs).
- + *
- + * NOTE: if kernel memory is low, newtimeout() will try to get a statically
- + * allocated timeout struct (fallback method).
- + */
- +
- + TIMEOUT * ARGS_ON_STACK
- + addtimeout(delta, func)
- + long delta;
- + void (*func) P_((PROC *));
- + {
- + TIMEOUT *t;
- +
- + t = newtimeout(0);
- +
- + /* BUG: we should have some fallback mechanism for timeouts when the
- + kernel memory is exhausted
- + */
- + assert(t);
- +
- + t->proc = curproc;
- + t->func = func;
- + inserttimeout(t, delta);
- + return t;
- + }
- +
- + /*
- + * addroottimeout(long delta, void (*)(PROC *), short flags);
- + * Same as addtimeout(), except that the timeout is attached to Pid 0 (MiNT).
- + * This means the timeout won't be cancelled if the process which was
- + * running at the time addroottimeout() was called exits.
- + *
- + * Currently only bit 0 of `flags' is used. Meaning:
- + * Bit 0 set: Call from interrupt (cannot use kmalloc, use statically
- + * allocated `struct timeout' instead).
- + * Bit 0 clear: Not called from interrupt, can use kmalloc.
- + *
- + * Thus addroottimeout() can be called from interrupts (bit 0 of flags set),
- + * which makes it *extremly* useful for device drivers.
- + * A serial device driver would make an addroottimeout(0, check_keys, 1)
- + * if some bytes have arrived.
- + * check_keys() is then called at the next context switch, can use all
- + * the kernel functions and can do time cosuming jobs.
- + */
- +
- + TIMEOUT * ARGS_ON_STACK
- + addroottimeout(delta, func, flags)
- + long delta;
- + void (*func) P_((PROC *));
- + short flags;
- + {
- + TIMEOUT *t;
- +
- + t = newtimeout(flags & 1);
- + if (!t) return NULL;
- + t->proc = rootproc;
- + t->func = func;
- + inserttimeout(t, delta);
- return t;
- }
-
- ***************
- *** 82,87 ****
- --- 175,181 ----
- {
- TIMEOUT *cur, **prev, *old;
- long delta;
- + short sr = spl7 ();
-
- cur = tlist;
- prev = &tlist;
- ***************
- *** 91,103 ****
- --- 185,203 ----
- old = cur;
- *prev = cur = cur->next;
- if (cur) cur->when += delta;
- + spl(sr);
- disposetimeout(old);
- + sr = spl7();
- + /* ++kay: just in case an interrupt handler installed a
- + * timeout right after `prev' and before `cur' */
- + cur = *prev;
- }
- else {
- prev = &cur->next;
- cur = cur->next;
- }
- }
- + spl (sr);
- }
-
- /*
- ***************
- *** 115,133 ****
- TIMEOUT *this;
- {
- TIMEOUT *cur, **prev;
-
- prev = &tlist;
- for (cur = tlist; cur; cur = cur->next) {
- ! if (cur == this && cur->proc == curproc) {
- *prev = cur->next;
- if (cur->next) {
- cur->next->when += this->when;
- }
- disposetimeout(this);
- ! break;
- }
- prev = &cur->next;
- }
- }
-
- /*
- --- 215,237 ----
- TIMEOUT *this;
- {
- TIMEOUT *cur, **prev;
- + short sr = spl7();
-
- prev = &tlist;
- for (cur = tlist; cur; cur = cur->next) {
- ! if (cur == this &&
- ! (cur->proc == curproc || cur->proc == rootproc)) {
- *prev = cur->next;
- if (cur->next) {
- cur->next->when += this->when;
- }
- + spl (sr);
- disposetimeout(this);
- ! return;
- }
- prev = &cur->next;
- }
- + spl(sr);
- }
-
- /*
- ***************
- *** 170,175 ****
- --- 274,280 ----
- long delta;
- void (*evnt) P_((PROC *));
- TIMEOUT *old;
- + short sr;
-
- /* do the once per second things */
- while (our_clock < 0) {
- ***************
- *** 180,201 ****
- reset_priorities();
- }
-
- /* see if there are outstanding timeout requests to do */
- while (tlist && ((delta = tlist->when) <= 0)) {
- p = tlist->proc;
- - TRACE(("doing timeout code for pid %d", p->pid));
- evnt = tlist->func;
- old = tlist;
- tlist = tlist->next;
- - disposetimeout(old);
- - /* call the timeout function */
- - (*evnt)(p);
- -
- /* if delta < 0, it's possible that the time has come for the next timeout
- ! to occur */
- if (tlist)
- tlist->when += delta;
- }
- }
-
- /*
- --- 285,313 ----
- reset_priorities();
- }
-
- + sr = spl7();
- /* see if there are outstanding timeout requests to do */
- while (tlist && ((delta = tlist->when) <= 0)) {
- p = tlist->proc;
- evnt = tlist->func;
- old = tlist;
- tlist = tlist->next;
- /* if delta < 0, it's possible that the time has come for the next timeout
- ! * to occur.
- ! * ++kay: moved this before the timeout fuction is called, in case the
- ! * timeout function installes a new timeout. */
- if (tlist)
- tlist->when += delta;
- + spl(sr);
- + /* ++kay: debug output at spl7 hangs the system, so moved it here */
- + TRACE(("doing timeout code for pid %d", p->pid));
- + disposetimeout(old);
- +
- + /* call the timeout function */
- + (*evnt)(p);
- + sr = spl7();
- }
- + spl(sr);
- }
-
- /*
- --8<----------------------------------------------------
-